package javabase.concurrent;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;

public class CASBasedCounter {

    private volatile long count;
    private final AtomicLongFieldUpdater<CASBasedCounter> fieldUpdater;

    public CASBasedCounter() {
        fieldUpdater = AtomicLongFieldUpdater.newUpdater(CASBasedCounter.class, "count");
    }

    public long value() {
        return count;
    }

    private boolean compareAndSet(CASBasedCounter counter, long oldVal, long newVal) {
        return fieldUpdater.compareAndSet(counter, oldVal, newVal);
    }

    public void increment() {
        long oldVal;
        long newVal;
        do {
            oldVal = count;
            newVal = count + 1;
        } while (!compareAndSet(this, oldVal, newVal));
    }

    public static void main(String[] args) throws Exception {
        final CASBasedCounter counter = new CASBasedCounter();
        Thread t;
        Set<Thread> threads = new HashSet<>();
        for (int i = 0; i < 20; i++) {
            t = new Thread(() -> {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                counter.increment();
            });
            threads.add(t);
        }

        for (int i = 0; i < 8; i++) {
            t = new Thread(() -> {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(counter.value());
            });
            threads.add(t);
        }


        for (Thread tmp : threads) {
            tmp.start();
        }
        for (Thread tmp : threads) {
            tmp.join();
        }

        // 启动并等待指定的线程结束
        System.out.println("final count:" + String.valueOf(counter.value()));
    }

}
